﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "GmepModelInterface.h"
#include "IMepGenericElement.h"
#include "GmepBuiltInParameterStaticVauleListItems.h"
#include "IParameter.h"
#include "UniIdentity.h"

namespace gmep
{
    class IConnectorManager;
    class IConnector;
    class IMepCurveType;
    enum class MepCurveSimplifyEnum;
    enum class MEPDisciplineId;

    struct BusinessParameterInfo
    {
    public:
        BusinessParameterInfo(const gcmp::ParameterAttributes &attributes, const gcmp::UniIdentity &definitionUid, gcmp::ParameterProcessType processType)
            :Attributes(attributes), DefinitionUid(definitionUid), ProcessType(processType) {}
    public:
        gcmp::ParameterAttributes Attributes;
        gcmp::UniIdentity DefinitionUid;
        gcmp::ParameterProcessType ProcessType;
    };

    class GMEP_MODEL_INTERFACE_EXPORT IMepCurve : public IMepGenericElement
    {
        DEFINE_CAST_DERIVED(gmep::IMepCurve, gmep::IMepGenericElement);

    public:
        /// \brief 析构函数
        virtual ~IMepCurve() {}

        // IMepCurve接口

        /// \brief 获取所属楼层Id
        ///
        /// \return  gmep::ElementId 返回获取所属楼层Id
        virtual gcmp::ElementId GetBuildingStoreyId() const = 0;

        /// \brief 设置获取所属楼层Id
        ///
        /// \param id 所属楼层Id
        /// \return bool 是否设置成功
        virtual bool SetBuildingStoreyId(const gcmp::ElementId& id) = 0;

        /// \brief 获得连接管理器
        /// \return const gmep::IConnectorManager * 返回连接管理器指针（const类型）
        virtual const IConnectorManager *GetConnectorManager() const = 0;

        /// \brief 获得连接管理器
        /// \return const gmep::IConnectorManager * 返回连接管理器指针
        virtual IConnectorManager* GetConnectorManager() = 0;

        /// \brief 设置连接点管理器
        /// \param gcmp::OwnerPtr<IConnectorManager> opConnectorManager 连接点管理器
        /// \return bool 返回是否设置成功
        virtual bool SetConnectorManager(gcmp::OwnerPtr<IConnectorManager> opConnectorManager) = 0;

        /// \brief 获取起点坐标
        /// \return gcmp::Vector3d 返回起点坐标点
        virtual gcmp::Vector3d GetStartPoint() const;

        /// \brief 设置起点坐标
        /// \param const gcmp::Vector3d & startPoint 起点坐标点
        /// \return bool 
        virtual bool SetStartPoint(const gcmp::Vector3d& startPoint);
        
        /// \brief 设置起点和终点坐标
        /// \param const gcmp::Vector3d & startPoint 起点坐标点
        /// \param const gcmp::Vector3d & endPoint   终点坐标点
        /// \return bool 
        virtual bool SetStartAndEndPoint(const gcmp::Vector3d& startPoint, const gcmp::Vector3d& endPoint);
        /// \brief 获得终点坐标
        /// \return gcmp::Vector3d  返回起点坐标点
        virtual gcmp::Vector3d GetEndPoint() const;
        
        /// \brief 设置终点坐标
        /// \param const gcmp::Vector3d & endPoint 终点坐标
        /// \return void 
        virtual bool SetEndPoint(const gcmp::Vector3d& endPoint);

        /// \brief 获取起点和终点坐标
        /// \return gcmp::Vector3d 返回起点和终点坐标点
        virtual bool GetStartAndEndPoint(gcmp::Vector3d& startPoint,gcmp::Vector3d& endPoint) const;

        /// \brief 获得关联平面ElementID
        /// \return gcmp::ElementId  返回关联平面ElementID
        virtual gcmp::ElementId GetAssociatedPlaneId() const;

        /// \brief  设置关联平面
        /// \param const gcmp::ElementId & associatedPlaneId 设置的关联平面ElementID
        /// \return bool 返回是否设置关联平面成功
        virtual bool SetAssociatedPlaneId(const gcmp::ElementId& associatedPlaneId);

        /// \brief 获取底部偏移高度
        /// \return double 返回底部偏移高度
        virtual double GetBottomOffset()const;

        /// \brief 设置底部偏移高度
        /// \param double offset 底部偏移高度
        /// \return bool  是否设置成功
        virtual bool SetBottomOffset(double offset);

        /// \brief 获得管道直径
        /// \return double 返回管道直径
        virtual double GetDiameter() const;

        /// \brief 设置管道直径
        /// \param double diameter 直径大小
        /// \return bool 返回是否设置成功
        virtual bool SetDiameter(double diameter);

        /// \brief 获得管道宽度
        /// \return double 返回管道宽度
        virtual double GetWidth() const;

        /// \brief 设置管道宽度
        /// \param double width 管道宽度
        /// \return bool 返回是否设置成功
        virtual bool SetWidth(double width);

        /// \brief 获得管道高度
        /// \return double 获得管道高度
        virtual double GetHeight() const;

        /// \brief 设置管道高度
        /// \param double height 设置的管道高度
        /// \return bool 返回是否设置成功
        virtual bool SetHeight(double height);

        /// \brief 获得管道类型
        /// \return const gmep::IMepCurveType* 返回管道类型指针
        virtual const IMepCurveType* GetMepCurveType() const;

        /// \brief 获得管道类型
        /// \return gmep::IMepCurveType* 返回管道类型指针
        virtual IMepCurveType* GetMepCurveType();

        /// \brief 获取管道系统ElementID
        /// \return gcmp::ElementId 返回管道系统ElementID
        virtual gcmp::ElementId GetMepSystemId() const = 0;

        /// \brief 获取管道系统类型ElementID
        /// \return gcmp::ElementId 返回管道系统类型ElementID
        virtual gcmp::ElementId GetMepSystemTypeId() const;


        /// \brief 获取管线所属的专业
        /// \return 返回管线所属的专业
        virtual gmep::MEPDisciplineId GetMepDiscipline() const = 0;

        /// \brief 获取管段ElementID
        /// \return gcmp::ElementId 返回管段ElementID
        virtual gcmp::ElementId GetMepCurveSegmentId() const;

        /// \brief 获取水平对正值
        ///
        /// \return gmep::HorizontalAlignment 返回水平对正值，默认为Center
        virtual gmep::HorizontalAlignment GetHorizontalAlignment() const { return HorizontalAlignment::Center; }

        /// \brief 设置水平对正
        ///
        /// \param hAlignment 水平对正值
        /// \return bool 返回是否设置成功
        virtual bool SetHorizontalAlignment(gmep::HorizontalAlignment hAlignment) { return false; }

        /// \brief 获取垂直对正值
        ///
        /// \return gmep::VerticalAlignment 返回垂直对正值，默认为Middle
        virtual gmep::VerticalAlignment GetVerticalAlignment() const { return VerticalAlignment::Middle; }

        /// \brief 设置垂直对正
        ///
        /// \param vAlignment 垂直对正值
        /// \return bool 返回是否设置成功
        virtual bool SetVerticalAlignment(gmep::VerticalAlignment vAlignment) { return false; }

        /// \brief 是否可以连接变径
        ///
        /// \return bool 是否可以连接变径
        virtual bool CanConnectedWithTransition() const { return true; }

        /// \brief 当存在管道删除后更新管道弱依赖关系
        /// \param const std::set<gcmp::ElementId> & deletedElementIds 表示将被删除的ElementIds
        /// \return void 
        virtual void UpdateForWeakParentDeletion(const std::set<gcmp::ElementId>& deletedElementIds) override;

        /// \brief 报告依赖的ElementIds
        /// \param gcmp::IElementParentReporter & elementParentReporter  Element关系报告器
        /// \return void 
        virtual void ReportParents(gcmp::IElementParentReporter& elementParentReporter) const override;

        /// \brief 定义IndependentLabelUpdateRdId的Get函数
        virtual RegenDataId GetIndependentParameterUpdateRdId()const = 0;

        /// \brief 标记tag更新RdId
        virtual void MarkIndependentParameterUpdateRdId() = 0;

        /// \brief 报告管线的内嵌业务参数
        virtual std::vector<BusinessParameterInfo> ReportBusinessEmbeddedParameters() const = 0;

        // TODO: 不需要暴露的接口，后续需要处理掉
    public:
        /// \brief 为管线添加ConnectorType::Curve类型的连接点
        ///
        /// 将传入点向管线定位线投影，只有投影点在管线上，才会在投影点处添加一个ConnectorType::Curve类型的连接点
        /// \param curveConnectorOrigin 管线上的一点或者附件的一点，用于创建连接点
        /// \return IConnector* 返回新创建的连接点，如果创建不成功，返回空指针
        virtual IConnector* AddCurveConnector(const gcmp::Vector3d& curveConnectorOrigin) = 0;

        /// \brief 删除管线上特定Id的类型为ConnectorType::Curve的连接点
        ///
        /// 注意只能删除类型为ConnectorType::Curve的连接点，不能删除管线的起末连接点（类型为ConnectorType::End）
        /// \param connectorId 待删除的连接点的Id
        /// \return bool 如果删除成功，返回true；否则返回false
        virtual bool RemoveCurveConnector(int connectorId) = 0;

        /// \brief 定义管线截面RegionData的Get和Mark函数
        virtual RegenDataId GetSectionSizeRdId() const = 0;
        virtual void MarkSectionSizeRdId() = 0;

        /// \brief 定义管线控制点RegionData的Get函数
        virtual RegenDataId GetPositionRdId() const = 0;

        /// \brief 定义管线参照平面RegionData的Get函数
        virtual RegenDataId GetReferencePlaneRdId() const = 0;

        /// \brief设置管道简化的枚举类型
        virtual bool SetCurveSimplifyEnum(MepCurveSimplifyEnum curveSimplifyEnum) = 0;

        /// \brief获得管道简化的枚举类型
        virtual MepCurveSimplifyEnum GetCurveSimplifyEnum()const = 0;

        /// \brief 返回材质名称
        std::wstring GetMaterialName(const gcmp::IDocument* pDoc)const;

        /// \brief 是否是立管
        /// 
        /// \param const gcmp::IModelView *pModelView 当前视图
        /// \return bool 是否是立管
        virtual bool IsVertical(const gcmp::IModelView *pModelView) const;

        /// \brief 定义系统类型编码更新RegionData的Get和Mark函数
        virtual RegenDataId GetMepSystemTypeChangeRdId() const = 0;
        virtual void MarkMepSystemTypeChangeRdId() = 0;
    };
}
